package com.asen.libcommon.util

import android.annotation.SuppressLint
import com.asen.libcommon.util.NumberUtil.formatInt00
import com.orhanobut.logger.Logger
import java.net.URL
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*


// 2006年11月17日 15时19分56秒
// SimpleDateFormat myFmt = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
// 06/11/17 15:19
// SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd HH:mm");
// 2006-11-17 15:19:56
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 2006年11月17日 15时19分56秒 星期五
// SimpleDateFormat myFmt3 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 E ");
//    //获取当前系统时间
//    //方法一
//    long startMillis=System.currentTimeMillis();
//    //方法二
//    long startTimeInMillis=Calendar.getInstance().getTimeInMillis();
//    //方法三
//    long startGetTime=new Date().getTime();

/**
 * @author : asenLiang
 * @date   : 2021/03/03
 * @e-mail : liangAisiSen@163.com
 * @desc   : 日期工具类
 */
object DateUtil {

    const val FORMAT_YYYY_MM_DD = "yyyy-MM-dd"
    const val FORMAT_YYYY_MM_DD_HH_mm = "yyyy-MM-dd HH:mm"
    const val FORMAT_YYYY_MM_DD_HH_mm_ss = "yyyy-MM-dd HH:mm:ss"
    const val FORMAT_HH_mm_ss = "HH:mm:ss"
    const val FORMAT_HH_mm = "HH:mm"

    /**
     * 日期格式字符串转换成时间戳
     * @param date 字符串日期
     */
    fun date2TimeStamp(date: String?): String {
        try {
            return SimpleDateFormat("yyyy-MM-dd").parse(date).time.toString()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return ""
    }

    /**
     * 获取百度官方时间
     */
    fun getBaiduTime(listener: OnInternetTimeListener) {
        Thread(Runnable {
            val webUrlBaidu = "http://www.baidu.com" //百度
            var url: URL? = null // 取得资源对象
            try {
                url = URL(webUrlBaidu)
                val uc = url.openConnection() // 生成连接对象
                uc.connect() // 发出连接
                val ld = uc.date // 读取网站日期时间
                val date = Date(ld) // 转换为标准时间对象
                //SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss, Locale.CHINA);// 输出北京时间
                listener.done(date, null)
            } catch (e: Exception) {
                e.printStackTrace()
                Logger.e("Exception:" + e.message)
                listener.done(null, e)
            }
        }).start()
    }

    /**
     * 获取淘宝官方时间
     */
    fun getTaobaoTime(listener: OnInternetTimeListener) {
        Thread(Runnable {
            val webUrlTaobao = "http://www.taobao.com" //淘宝
            var url: URL? = null // 取得资源对象
            try {
                url = URL(webUrlTaobao)
                val uc = url.openConnection() // 生成连接对象
                uc.connect() // 发出连接
                val ld = uc.date // 读取网站日期时间
                val date = Date(ld) // 转换为标准时间对象
                //SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss, Locale.CHINA);// 输出北京时间
                listener.done(date, null)
            } catch (e: Exception) {
                e.printStackTrace()
                Logger.e("Exception:" + e.message)
                listener.done(null, e)
            }
        }).start()
    }

    /**
     * 以现在为标准，向后推延指定month的数量
     *
     * @param months 向后推延的月数
     * @return String[], 0下标是年，1下标是月，2下标是日
     */
    fun getDateByMonths(months: Int): IntArray = getDateByMonths(yearInt, monthInt, dayInt, months)

    /**
     * 以某个日期为标准，向后推延指定month的数量  比如2019 05 05 向后推3个月 就是 2019 02 05
     *
     * @param targetYear  指定年份
     * @param targetMonth 指定月
     * @param targetDay   指定日
     * @param months      向后推延的月数
     * @return String[], 0下标是年，1下标是月，2下标是日
     */
    fun getDateByMonths(targetYear: Int, targetMonth: Int, targetDay: Int, months: Int): IntArray {

        var targetDay = targetDay
        var mYear = targetYear
        val sumMonth = targetMonth + months

        if (sumMonth > 12) {
            val newYear = sumMonth / 12
            mYear += newYear
        }

        var finalMonth = sumMonth % 12

        if (finalMonth == 0) finalMonth = 12

        if (targetDay == 31)
            if (finalMonth == 4 || finalMonth == 6 || finalMonth == 9 || finalMonth == 11)
                targetDay = 30

        if (targetDay > 28)
            if (finalMonth == 2)
                targetDay = if (isRunNian(mYear)) 29 else 28

        return intArrayOf(mYear, finalMonth, targetDay)

    }

    /**
     * @param time 某个时间
     * @return String yyyy年MM月dd日 HH时mm分ss秒
     * yyyy-MM-dd HH:mm:ss
     * yy/MM/dd HH:mm
     */
    fun parseTimeYYYYMMDDHHMMSS(time: Long) =
        SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss).format(Date(time))

    /**
     * @param time 某个时间
     * @return String yyyy年MM月dd日 HH时mm分ss秒
     * yyyy-MM-dd HH:mm:ss
     * yy/MM/dd HH:mm
     */
    fun parseTimeYYYYMMDD(time: Long) = SimpleDateFormat(FORMAT_YYYY_MM_DD).format(Date(time))

    /**
     * 指定格式返回当前系统时间
     *
     * @param format yyyy年MM月dd日 HH时mm分ss秒
     * yyyy-MM-dd HH:mm:ss
     * yy/MM/dd HH:mm
     * 等等
     */
    fun getDataTime(format: String?)= SimpleDateFormat(format).format(Date())

    /**
     * 得到当前年
     */
    val year: Int
        get() = SimpleDateFormat("yyyy").format(System.currentTimeMillis()).toInt()

    /**
     * 得到当前年
     */
    val yearInt: Int get() = yearString.toInt()

    /**
     * 得到当前年
     */
    val yearString: String get() = SimpleDateFormat("yyyy").format(System.currentTimeMillis())

    /**
     * 得到当前月份 int
     */
    val monthInt: Int get() = monthString.toInt()

    /**
     * 得到当前月份 string
     */
    val monthString: String
        get() {
            val currentTime = SimpleDateFormat(FORMAT_YYYY_MM_DD).format(System.currentTimeMillis())
            return currentTime.substring(5, 7)
        }

    /**
     * 得到今天日期 int
     */
    val dayInt: Int get() = dayString.toInt()

    /**
     * 得到今天日期 string
     */
    val dayString: String
        get() {
            val currentTime = SimpleDateFormat(FORMAT_YYYY_MM_DD).format(System.currentTimeMillis())
            return currentTime.substring(8, currentTime.length)
        }

    /**
     * 得到今天日期  小时 int
     */
    val hourInt: Int get() = hourString.toInt()

    /**
     * 得到今天日期  小时 string
     */
    val hourString: String get() = getYYYYMMDDHHMMSS(System.currentTimeMillis()).substring(11, 13)

    /**
     * 得到今天日期  分钟 int
     */
    val minuteInt: Int get() = minuteString.toInt()

    /**
     * 得到今天日期  分钟 string
     */
    val minuteString: String get() = getYYYYMMDDHHMMSS(System.currentTimeMillis()).substring(14, 16)

    /**
     * 得到某天日期 String
     * "yyyy-MM-dd HH:mm:ss"
     */
    fun getYYYYMMDDHHMMSS(time: Long): String = SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss).format(time)

    /**
     * 得到某天日期 String
     * "yyyy-MM-dd HH:mm:ss"
     */
    val todayYYYYMMDDHHMMSS: String get() =  SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss).format(System.currentTimeMillis())

    //===========================================================
    //基本工具
    //===========================================================

    /**
     * year 是否是闰年
     */
    fun isRunNian(year: Int): Boolean {
        return year % 4 == 0 && year % 100 != 0 || year % 400 == 0
    }

    /**
     * 返回指定年指定月份的天数
     * @param year,month 指定年，指定月
     */
    fun getMonthDays(year: Int, month: Int): Int {
        if (isRunNian(year)) {
            // 这是闰年
            if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
                return 31 // 31
            } else if (month == 4 || month == 6 || month == 9 || month == 11) {
                return 30 // 30
            } else if (month == 2) {
                return 29 // 2月 29天
            }
        } else {
            // 这是平年
            return if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
                31 // 31
            } else if (month == 4 || month == 6 || month == 9 || month == 11) {
                30 // 30
            } else {
                28 // 2月 28天
            }
        }
        return 0
    }

    //===========================================================
    //星期转换
    //===========================================================

    const val WEEKDAYS = 7
    var WEEK_STRING_EN = arrayOf("SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY")
    var WEEK_STRING_ZH = arrayOf("星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六")
    var WEEK_INT = intArrayOf(0, 1, 2, 3, 4, 5, 6)

    /**
     * 日期变量转成对应的星期字符串
     * @param date 日期对象
     * @return String 星期几
     */
    fun formatWeekEn(date: Date?): String? {
        val calendar = Calendar.getInstance()
        calendar.time = date
        val dayIndex = calendar[Calendar.DAY_OF_WEEK]
        return if (dayIndex < 1 || dayIndex > WEEKDAYS) null else WEEK_STRING_EN[dayIndex - 1]
    }

    /**
     * 日期变量转成对应的星期字符串
     * @param date 日期对象
     * @return String 星期几
     */
    fun formatWeekZh(date: Date?): String? {
        val calendar = Calendar.getInstance()
        calendar.time = date
        val dayIndex = calendar[Calendar.DAY_OF_WEEK]
        return if (dayIndex < 1 || dayIndex > WEEKDAYS) null else WEEK_STRING_ZH[dayIndex - 1]
    }

    /**
     * 日期变量转成对应的星期字符串
     * @param date 日期对象
     * @return int 返回-1时，说明传递的参数有错 正常是0，1，2，3，4，5，6
     */
    fun dayOfWeekInt(date: Date?): Int {
        val calendar = Calendar.getInstance()
        calendar.time = date
        val dayIndex = calendar[Calendar.DAY_OF_WEEK]
        return if (dayIndex < 1 || dayIndex > WEEKDAYS) -1 else WEEK_INT[dayIndex - 1]
    }

    //===========================================================
    //日期间隔
    //===========================================================

    /**
     * 获取指定日期时间戳
     * @param date 指定日期
     * @param type 格式
     */
    fun getDateLong(date: String?, type: String?): Long {
        val sdf = SimpleDateFormat(type)
        var before: Date? = null
        try {
            before = sdf.parse(date)
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return before!!.time
    }

    /**
     * 判断一个日期和现在隔了多少天
     * @param targetDate 指定日期 格式为："yyyy-MM-dd HH:mm:ss"
     */
    @Throws(ParseException::class)
    fun getBeApartDay(targetDate: String?): Long {
        val sdf = SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss)
        val before = sdf.parse(targetDate)
        val nowString = sdf.format(System.currentTimeMillis())
        val now = sdf.parse(nowString)
        var day = Math.abs(now.time - before.time) / (24 * 60 * 60 * 1000)
        if (before.time < now.time) {
            day -= day * 2
        }
        return day
    }

    /**
     * 判断一个日期和现在隔了多少小时
     * @param targetDate 指定日期 格式为："yyyy-MM-dd HH:mm:ss"
     */
    @Throws(ParseException::class)
    fun getBeApartHours(targetDate: String?): Long {
        val sdf = SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss)
        val before = sdf.parse(targetDate)
        val nowString = sdf.format(System.currentTimeMillis())
        val now = sdf.parse(nowString)
        return (now.time - before.time) / (60 * 60 * 1000)
    }

    /**
     * 判断一个日期和现在隔了多少分种
     * @param targetDate 指定日期 格式为："yyyy-MM-dd HH:mm:ss"
     */
    @Throws(ParseException::class)
    fun getBeApartMinute(targetDate: String?): Long {
        val sdf = SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss)
        val before = sdf.parse(targetDate)
        val nowString = sdf.format(System.currentTimeMillis())
        val now = sdf.parse(nowString)
        return (now.time - before.time) / (60 * 1000)
    }

    /**
     * 判断两个日期隔了多少天 格式为 yyyy-MM-dd
     * @param start 开始日期
     * @param end   结束日期
     */
    @Throws(ParseException::class)
    fun getTwoDatesBeApart(start: String?, end: String?): Long {
        val sdf = SimpleDateFormat(FORMAT_YYYY_MM_DD)
        val before = sdf.parse(start)
        val now = sdf.parse(end)
        return (now.time - before.time) / (24 * 60 * 60 * 1000)
    }

    /**
     * 转换成  查日报列表所要的时间
     * @param formatString 制定返回的格式 如"yyyy-MM-dd"
     * @param year         年
     * @param month        月
     * @param day          日
     */
    fun formatDate(formatString: String?, year: Int, month: Int, day: Int): String {
        val dateFormat = SimpleDateFormat(formatString)
        val date = Date()
        date.year = year - 1900
        date.month = month - 1
        date.date = day
        return dateFormat.format(date)
    }

    //===========================================================
    //得到多少天以前的日期
    //===========================================================

    /**
     * 得到 以今天为标准的前一天的 日期
     * @return String[] 下标0是年，下标1是月，下标2是日
     */
    val previous1Today: Array<String> get() = getPrevious1Day(yearInt, monthInt, dayInt)

    /**
     * 得到 以今天为标准的前两天的 日期
     * @return String[] 下标0是年，下标1是月，下标2是日
     */
    val previous2Today: Array<String> get() = getPrevious2Day(yearInt, monthInt, dayInt)

    /**
     * 得到 以某天为标准的，前一天的 日期
     * @return String[] 下标0是年，下标1是月，下标2是日
     */
    fun getPrevious1Day(year: Int, month: Int, day: Int): Array<String> {
        val yearTemp: Int
        val monthTemp: Int
        val dayTemp: Int
        if (day == 1) {
            if (month == 1) {
                monthTemp = 12
                yearTemp = year - 1
            } else {
                monthTemp = month - 1
                yearTemp = year
            }
            dayTemp = getMonthDays(yearTemp, monthTemp)
        } else {
            yearTemp = year
            monthTemp = month
            dayTemp = day - 1
        }
        return arrayOf(yearTemp.toString(), formatInt00(monthTemp), formatInt00(dayTemp))

    }

    /**
     * 得到 以某天为标准的，下一天的 日期  格式 为"yyyy-MM-dd"
     * @return String[] 下标0是年，下标1是月，下标2是日
     */
    fun getNext1Day(year: Int, month: Int, day: Int): Array<String> {
        val c = Calendar.getInstance()
        var date: Date? = null
        try {
            date = SimpleDateFormat(FORMAT_YYYY_MM_DD).parse(year.toString() + "-" + formatInt00(month) + "-" + formatInt00(day))
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        c.time = date
        val mDay = c[Calendar.DATE]
        c[Calendar.DATE] = mDay + 1
        @SuppressLint("SimpleDateFormat")
        val dayAfter = SimpleDateFormat(FORMAT_YYYY_MM_DD).format(c.time)

        return arrayOf(dayAfter.substring(0, 4), dayAfter.substring(5, 7), dayAfter.substring(8, dayAfter.length))

    }

    /**
     * 得到 以某天为标准的，前两天的 日期
     * @return String[] 下标0是年，下标1是月，下标2是日
     */
    fun getPrevious2Day(year: Int, month: Int, day: Int): Array<String> {
        val yearTemp: Int
        val monthTemp: Int
        val dayTemp: Int
        when (day) {
            1 -> {
                if (month == 1) {
                    monthTemp = 12
                    yearTemp = year - 1
                } else {
                    monthTemp = month - 1
                    yearTemp = year
                }
                dayTemp = getMonthDays(yearTemp, monthTemp) - 1
            }
            2 -> {
                if (month == 1) {
                    monthTemp = 12
                    yearTemp = year - 1
                } else {
                    monthTemp = month - 1
                    yearTemp = year
                }
                dayTemp = getMonthDays(yearTemp, monthTemp)
            }
            else -> {
                yearTemp = year
                monthTemp = month
                dayTemp = day - 2
            }
        }
        return arrayOf(yearTemp.toString(), formatInt00(monthTemp), formatInt00(dayTemp))
    }

    //===========================================================
    //===========================================================

    /**
     * 获取过去第几天的日期  格式 为"yyyy-MM-dd"
     * @param past
     */
    fun getPastDate(past: Int): String {
        val calendar = Calendar.getInstance()
        calendar[Calendar.DAY_OF_YEAR] = calendar[Calendar.DAY_OF_YEAR] - past
        val today = calendar.time
        val format =
            SimpleDateFormat(FORMAT_YYYY_MM_DD)
        return format.format(today)
    }

    /**
     * 获取未来 第 past 天的日期  格式 为"yyyy-MM-dd"
     * @param past
     */
    fun getFetureDate(past: Int): String {
        val calendar = Calendar.getInstance()
        calendar[Calendar.DAY_OF_YEAR] = calendar[Calendar.DAY_OF_YEAR] + past
        val today = calendar.time
        return SimpleDateFormat(FORMAT_YYYY_MM_DD).format(today)
    }

    //===========================================================
    //JAVA与PHP
    //===========================================================

    /**
     * 得到某天日期 String
     * @param time 后面比php多3个0 TODO:为"yyyy-MM-dd"的格式
     */
    fun getDateByFormat(time: Long, format: String?): String = SimpleDateFormat(format).format(time)

    /**
     * 得到某天日期 String
     * "yyyy-MM-dd"
     * * @param time 后面比php多3个0
     */
    fun getDateYYYYMMDD_java(time: Long): String = if (time == 0L) "-" else SimpleDateFormat(FORMAT_YYYY_MM_DD).format(time)

    fun getDateYYYYMMDDhhmm_java(time: Long): String = if (time == 0L) "" else SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm).format(time)

    fun getDateYYYYMMDDhhmmss_java(time: Long): String = if (time == 0L)  "" else  SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss).format(time)

    fun getDateType(time: Long, type: String?): String = if (time == 0L) "" else SimpleDateFormat(type).format(time)

    fun getDatehhmmss_java(time: Long): String = if (time == 0L) "" else SimpleDateFormat(FORMAT_HH_mm_ss).format(time)

    fun getDatehhmm_java(time: Long): String = if (time == 0L) "" else SimpleDateFormat(FORMAT_HH_mm).format(time)

    /**
     * 得到某天日期 String
     * @param time 后面要补3个0 TODO:为"yyyy-MM-dd"的格式
     */
    fun getDateYYYYMMDD_php(time: Long): String = SimpleDateFormat(FORMAT_YYYY_MM_DD).format(java.lang.Long.valueOf(time.toString() + "000"))

    /**
     * 得到某天日期 String
     * @param time 后面要补3个0 TODO:为"yyyy-MM-dd"的格式
     */
    fun getDateYYYYMMDDHHMM_php(time: Long): String
        = SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm).format(java.lang.Long.valueOf(time.toString() + "000"))

    /**
     * 得到某天日期 long
     * @param time 为"yyyy-MM-dd"的格式
     */
    fun getDateByYYYYMMDD_java(time: String?): Long {
        try {
            return SimpleDateFormat(FORMAT_YYYY_MM_DD).parse(time).time
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return 0
    }

    /**
     * 得到某天日期 long
     * @param time 为"yyyy-MM-dd"的格式
     */
    fun getDayDateByYYYYMMDDHHMMss_java(time: String?): Long {
        try {
            return SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm_ss).parse(time).time
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return 0
    }

    /**
     * 得到某天日期 long
     * @param time 为"yyyy-MM-dd"的格式
     */
    fun getDayDateByYYYYMMDDHHMM_java(time: String?): Long {
        try {
            return SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm).parse(time).time
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return 0
    }

    /**
     * 得到某天日期 long
     * @param time 为"yyyy-MM-dd"的格式
     */
    fun getDayDateByYYYYMMDD_java(time: String?): Long {
        try {
            return SimpleDateFormat(FORMAT_YYYY_MM_DD).parse(time).time
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return 0
    }

    /**
     * 得到某天日期 long
     * @param time 为"yyyy-MM-dd"的格式
     */
    fun getDateByYYYYMMDD_php(time: String?): Long {
        try {
            val stringTime = SimpleDateFormat(FORMAT_YYYY_MM_DD).parse(time).time.toString()
            return stringTime.substring(0, stringTime.length - 3).toLong()
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return 0
    }

    /**
     * 得到某天日期 long
     * @param time 为"yyyy-MM-dd"的格式
     */
    fun getDayDateByYYYYMMDDHHMM_php(time: String?): Long {
        try {
            val stringTime = SimpleDateFormat(FORMAT_YYYY_MM_DD_HH_mm).parse(time).time.toString()
            return stringTime.substring(0, stringTime.length - 3).toLong()
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return 0
    }

    /** 得到今天日期 String 格式 "yyyy-MM-dd" */
    val todayYYYYMMDD: String get() = getDateYYYYMMDD_java(System.currentTimeMillis())

    /** 得到今天日期 String 格式 "yyMMdd" */
    val todayYYMMDD: String get() = SimpleDateFormat("yyMMdd").format(System.currentTimeMillis())

    interface OnInternetTimeListener {
        fun done(date: Date?, e: Exception?)
    }

}